package services

import (
	"errors"
	"gitee.com/damengde/treebark/mapper"
	"gitee.com/damengde/treebark/model"
	"gitee.com/damengde/treebark/util"
)

func NewDefaultService[T any](mapper mapper.DBMapper[T], nodeField *model.NodeField) *TreeServiceImpl[T] {
	return &TreeServiceImpl[T]{
		mapper:    mapper,
		nodeField: nodeField,
	}
}

type TreeServiceImpl[T any] struct {
	mapper    mapper.DBMapper[T]
	nodeField *model.NodeField
}

// QueryDescendentById 查询指定父节点下的所有子节点
func (t *TreeServiceImpl[T]) QueryDescendentById(id any) ([]*T, error) {
	return t.mapper.SelectDescendentById(id)
}
func (t *TreeServiceImpl[T]) Create(node *T) error {

	//根节点直接插入
	if util.IsEmpty(t.nodeField.GetParentId(node)) {
		t.nodeField.SetLeft(node, 1)
		t.nodeField.SetRight(node, 2)
		return t.mapper.SaveOrUpdate(node)
	}

	// 查询父节点
	parentId := t.nodeField.GetParentId(node)
	pMod, err := t.mapper.SelectById(parentId)
	if err != nil {
		return err
	}
	// 取出树id
	treeId := t.nodeField.GetTreeId(pMod)
	// 查询树的所有节点并锁定
	allNodes, err := t.mapper.SelectDescendentAndLockByTreeId(treeId)
	if err != nil {
		return errors.New("查询部门信息失败：" + err.Error())
	}

	// 重新编号
	if err = t.addReNumber(node, allNodes, parentId); err != nil {
		return err
	}

	// 保存节点
	if err = t.mapper.SaveOrUpdate(node); err != nil {
		return err
	}
	// 更新所有节点
	return t.mapper.UpdateBatch(allNodes)
}

// addReNumber
func (t *TreeServiceImpl[T]) addReNumber(mod *T, allNodes []*T, parentId any) error {
	var flag bool
	for i, _ := range allNodes {
		// 所有节点  Right + 2
		t.nodeField.SetRight(allNodes[i], t.nodeField.GetRight(allNodes[i])+2)
		if flag {
			// 后续节点 Left + 2 Right+2
			t.nodeField.SetLeft(allNodes[i], t.nodeField.GetLeft(allNodes[i])+2)
			continue
		}
		// 找到父节点
		id := t.nodeField.GetID(allNodes[i])
		if id == parentId {
			flag = true
			// 父节点 Left + 1 代表最左边子节点，新节点默认插入父节点最左边
			lef := t.nodeField.GetLeft(allNodes[i]) + 1
			t.nodeField.SetLeft(mod, lef)
			// 新节点 Right + 1 新建节点下绝对没有子节点，所以新节点Left + 1就是新节点的Right
			t.nodeField.SetRight(mod, lef+1)
		}
	}
	// 判读有没有找到父节点
	if !flag {
		return errors.New("没有找到父节点")
	}
	return nil
}

func (t *TreeServiceImpl[T]) DeleteById(id any) error {
	// 查询删除的节点
	mod, err := t.mapper.SelectById(id)
	if err != nil {
		return err
	}

	//判断该节点下是否还有子节点
	hasNodes, err := t.mapper.SelectDescendentById(id)
	if err != nil {
		return err
	}
	if len(hasNodes) > 0 {
		return errors.New("该节点下还有子节点，不能删除")
	}

	//根节点直接删除
	if util.IsEmpty(t.nodeField.GetParentId(mod)) {
		return t.mapper.DeleteById(id)
	}
	// 取出顶级节点
	topId := t.nodeField.GetTreeId(mod)
	// 查询树的所有节点并锁定
	allNodes, err := t.mapper.SelectDescendentAndLockByTreeId(topId)
	if err != nil {
		return errors.New("查询部门信息失败：" + err.Error())
	}
	t.delReNumber(id, allNodes)
	// 先执行更新
	err = t.mapper.UpdateBatch(allNodes)
	if err != nil {
		return err
	}
	// 后删除节点
	return t.mapper.DeleteById(id)
}

// delReNumber 重新编号
func (t *TreeServiceImpl[T]) delReNumber(id any, allNodes []*T) {
	var flag bool
	for i, _ := range allNodes {
		// 找到节点
		if t.nodeField.GetID(allNodes[i]) == id {
			flag = true
			continue
		}
		// 所有节点  Right - 2
		t.nodeField.SetRight(allNodes[i], t.nodeField.GetRight(allNodes[i])-2)
		if flag {
			// 后续节点 Left - 2 Right-2
			t.nodeField.SetLeft(allNodes[i], t.nodeField.GetLeft(allNodes[i])-2)
		}
	}
}

// Rebuild 修正整棵树
func (t *TreeServiceImpl[T]) Rebuild() error {
	// 取出所有顶级父节点
	mods, err := t.mapper.SelectAllTopParentId()
	if err != nil {
		return err
	}
	for _, mod := range mods {
		topParentId := t.nodeField.GetID(mod)
		RebuildError := t.RebuildByTopParentId(topParentId)
		if RebuildError != nil {
			return RebuildError
		}
	}
	return nil
}

// CalLftRgtValue 计算左右指针的值
func (t *TreeServiceImpl[T]) CalLftRgtValue(startCount *int64, tree *model.TreeNode[T]) {
	if tree == nil {
		return
	}
	*startCount++
	t.nodeField.SetLeft(tree.Info, *startCount)

	// 遍历子节点
	for _, child := range tree.Children {
		t.CalLftRgtValue(startCount, child)
	}
	*startCount++
	t.nodeField.SetRight(tree.Info, *startCount)
}

// BuildTree 构建树
func (t *TreeServiceImpl[T]) BuildTree(nodeId any, mods []*T) (tree *model.TreeNode[T], err error) {
	nodeMap := make(map[any]*model.TreeNode[T])
	for _, mod := range mods {
		newNode := model.TreeNode[T]{
			Info: mod,
		}
		id := t.nodeField.GetID(mod)
		nodeMap[id] = &newNode
	}
	for _, mod := range mods {
		if t.nodeField.GetParentId(mod) != "" {
			parentNode := nodeMap[t.nodeField.GetParentId(mod)]
			parentNode.Children = append(parentNode.Children, nodeMap[t.nodeField.GetID(mod)])
		}
	}
	return nodeMap[nodeId], nil
}

// saveTreeNode 保存树节点
func (t *TreeServiceImpl[T]) saveTreeNode(tree *model.TreeNode[T]) error {
	if updateErr := t.mapper.UpdateNewNode(tree.Info); updateErr != nil {
		return updateErr
	}
	if len(tree.GetChildren()) > 0 {
		for _, child := range tree.GetChildren() {
			err := t.saveTreeNode(child)
			if err != nil {
				return err
			}
		}
	}
	return nil
}

// PartialRebuild 修正特定的树
func (t *TreeServiceImpl[T]) PartialRebuild(treeId any) error {
	// 查找该棵树的top_prent_id
	nodeInfo, SelectError := t.mapper.SelectById(treeId)
	if SelectError != nil {
		return SelectError
	}
	topParentId := t.nodeField.GetTreeId(nodeInfo)
	RebuildError := t.RebuildByTopParentId(topParentId)
	if RebuildError != nil {
		return RebuildError
	}
	return nil
}

// RebuildByTopParentId 根据topParentId来修复指定的树
func (t *TreeServiceImpl[T]) RebuildByTopParentId(topParentId any) error {
	nodes, selectError := t.mapper.SelectAllByParentIdAsc(topParentId)
	if selectError != nil {
		return selectError
	}
	// 构建树
	id := t.nodeField.GetID(nodes[0])
	tree, buildError := t.BuildTree(id, nodes)
	if buildError != nil {
		return buildError
	}
	// 计算左右指针数，更新tree数据
	t.CalLftRgtValue(new(int64), tree)
	// 保存
	saveErr := t.saveTreeNode(tree)
	if saveErr != nil {
		return saveErr
	}
	return nil
}
